package org.yuzuojian.com.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.yuzuojian.com.pojo.*;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class CglibDynamicAopProxy  implements MethodInterceptor {
    private Class clazz;
    private Map<Class, Mapper> cache;
    private SqlSessionFactory sqlSessionFactory;
    public Class getClazz() {
        return clazz;
    }

    public CglibDynamicAopProxy(Class clazz,Map<Class, Mapper> cache,SqlSessionFactory sqlSessionFactory) {
        this.clazz = clazz;
        this.cache = cache;
        this.sqlSessionFactory = sqlSessionFactory;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }

    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(this.clazz);
        //设置回调
        enhancer.setCallback(this);
        //设置类加载器
        enhancer.setClassLoader(this.clazz.getClassLoader());
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Mapper mapper = cache.get(clazz);
        //Parameter[] parameters = method.getParameters();
        Map<String, Function> functions = mapper.getFunctions();
        Map<String, ResultMap> resultMaps = mapper.getResultMaps();
        Function function = functions.get(method.getName());
        if(function.getSqlType().equals("select")){
            String resultMapId = function.getResultMap();
            ResultMap resultMap = resultMaps.get(resultMapId);
            Class<?> consumerClass = Class.forName(resultMap.getType());
            List<Result> results = resultMap.getResults();
            Id idResult = resultMap.getIdResult();
            List<Object> consumers = new ArrayList<>();
            Connection connection = sqlSessionFactory.getMybatisConfig().getDataSource().getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(function.getSql());
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()){
                Object o1 = consumerClass.newInstance();
                for (Result result : results) {
                    if(result.getJdbcType().equals("Integer")){
                        int anInt = resultSet.getInt(result.getColumn());
                        Field declaredField = consumerClass.getDeclaredField(result.getProperty());
                        declaredField.setAccessible(true);
                        declaredField.set(o1,anInt);
                    }else{
                        String string = resultSet.getString(result.getColumn());
                        Field declaredField = consumerClass.getDeclaredField(result.getProperty());
                        declaredField.setAccessible(true);
                        declaredField.set(o1,string);
                    }
                }
                if(idResult.getJdbcType().equals("Integer")){
                    int anInt = resultSet.getInt(idResult.getColumn());
                    Field declaredField = consumerClass.getDeclaredField(idResult.getProperty());
                    declaredField.setAccessible(true);
                    declaredField.set(o1,anInt);
                }else{
                    String string = resultSet.getString(idResult.getColumn());
                    Field declaredField = consumerClass.getDeclaredField(idResult.getProperty());
                    declaredField.setAccessible(true);
                    declaredField.set(o1,string);
                }
                consumers.add(o1);
            }
            return consumers;
        }
        return null;
    }
}